package org.game;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;

public class Level {
	static enum lightingType{
		ambient,
		ambientDiffuse,
		diffuse
	}
	lightingType _lightingType;
	String resource;
	float[] ambientLight;
	float[] clearColor;
	ArrayList<File> fileStorage;
	ArrayList<GameObject> levelObjects;
	boolean usingCamera;
	/** Create a level from a file
	 * 
	 * @param resource the location of the file to create the level by
	 */
	public Level(String resource){
		this.resource = resource;
		IOManager.include(resource);
		getValues();
	}
	/**Create a level from a file
	 * 
	 * @param file the file of the level
	 */
	public Level(File file){
		this.resource = file.getPath();
		if(!IOManager.has(file)){
			IOManager.include(file);
		}
		getValues();
	}
	/** Get the form which the level is lit.
	 * 
	 * @return the lightingType of the level
	 */
	public lightingType getLightingType(){
		return _lightingType;
	}
	/** Get a String output of the level's 
	 * specific variables
	 *  @return the contents of the level
	 */
	public String toString(){
		return "lightingType:"+_lightingType.toString();
	}
	/**
	 * Load the level from file
	 */
	private void getValues(){
		String[] values = IOManager.getFileContents(resource, ";");
		StringBuilder variables = new StringBuilder();
		StringBuilder types = new StringBuilder();
		for(String string: values){
			String[] key = string.split(":");
			variables.append(key[0]+";");
			types.append(key[1]+";");
		}
		String[] vars = variables.toString().split(";");
		String[] answ = types.toString().split(";");
		boolean clearColorSet = false;
		HashMap<String,File> references = new HashMap<String,File>();
		for(int i=0;i<vars.length;i++){
			if(answ[i].startsWith(" ")){
				answ[i] = answ[i].split(" ")[1];
			}
			switch(vars[i]){
			case "usesCamera":
				usingCamera = Boolean.parseBoolean(answ[i]);
			break;
			case "lighting":
				if(answ[i].startsWith(" ")){
					answ[i] = answ[i].split(" ")[1];
				}
				switch(answ[i]){
				case "ambient":
					_lightingType = lightingType.ambient;
				break;
				case "ambientDiffuse":
					_lightingType = lightingType.ambientDiffuse;
				break;
				case "diffuse":
					_lightingType = lightingType.diffuse;
				break;
				}
			break;
			case "shader":
				String[] shaderValues = answ[i].split(",");
				if(shaderValues[0].startsWith("<")){
					shaderValues[0] = references.get(shaderValues[0].split("<")[1].split(">")[0]).getPath();
				}
				if(shaderValues[1].startsWith("<")){
					shaderValues[1] = references.get(shaderValues[1].split("<")[1].split(">")[0]).getPath();
				}
				if(IOManager.exists(shaderValues[0]) && IOManager.exists(shaderValues[1])){				
					int id = ShaderLoader.loadProgram(shaderValues[0], shaderValues[1]);
					Game.storeShader(shaderValues[2],id);
				}else{
					if(IOManager.exists(shaderValues[0])){
						System.err.println("Vertex shader at line["+i+"] does not exist.");
					}else{
						System.err.println("Fragment shader at line["+i+"] does not exist.");
					}
				}
			break;
			case "clearColor":
				clearColorSet = true;
				if(answ[i].startsWith(" ")){
					answ[i] = answ[i].split(" ")[1];
				}
				String[] clear = answ[i].split(",");
				clearColor = new float[]{
					Float.valueOf(clear[0]),
					Float.valueOf(clear[1]),
					Float.valueOf(clear[2]),
					Float.valueOf(clear[3])
				};
			break;	
			case "object":
				String[] parameters = answ[i].split(",");
				if(IOManager.exists(parameters[0])){
					
				}else if(parameters[0].startsWith("<")){
					String raw = parameters[0].split("<")[1].split(">")[0];
					if(references.containsKey(raw)){
						GameObject custom = gameObjectFromFile(references.get(raw));
					}else{
						System.err.println("File reference "+raw+" at line ["+i+"] does not exist.");
					}
				}else{
					switch(parameters[0]){
						case "player":
							
						break;
						case "staticObject":
							
						break;
					}
				}
			break;
			case "objects":
				if(levelObjects == null){
					levelObjects = new ArrayList<GameObject>();
				}
				if(answ[i].startsWith("<")){
					String raw = answ[i].split("<")[1].split(">")[0];
					if(references.containsKey(raw)){
						fileStorage.clear();
						recursive(references.get(raw).getPath());
						for(int f=0;f<fileStorage.size();f++){
							levelObjects.add(gameObjectFromFile(fileStorage.get(f)));
						}
					}else{
						System.err.println("Error ["+i+"]: File reference "+raw+" has not been defined.");
					}
				}else if(IOManager.exists(answ[i])){
					fileStorage.clear();
					recursive(answ[i]);
					for(int f=0;f<fileStorage.size();f++){
						levelObjects.add(gameObjectFromFile(fileStorage.get(f)));
					}
					
				}else{
					System.err.println("Error ["+i+"]: Null reference:"+answ[i]+".");
				}
			break;
			case "script":
				if(answ[i].contains(",")){
					answ[i] = answ[i].split(",")[0];
				}
				IOManager.include(answ[i]);
			break;
			case "ambientLight":
				String[] rgba = answ[i].split(",");
				ambientLight = new float[]{
					Float.valueOf(rgba[0]),
					Float.valueOf(rgba[1]),
					Float.valueOf(rgba[2]),
					Float.valueOf(rgba[3])
				};
				break;
			case "file":
				String[] fileRef = answ[i].split(",");
				if(IOManager.exists(fileRef[1])){
					references.put(fileRef[0],new File(fileRef[1]));
				}else{
					System.err.println("Error on line["+i+"]: of " +resource+" file:"+fileRef[1]+" does not exist.");
				}
			break;
			case "filelist":
				String[] fileListInfo = answ[i].split(",");
				if(IOManager.exists(fileListInfo[1])){
					File fileListPath = new File(fileListInfo[1]);
					File[] fileList = fileListPath.listFiles();
					switch(fileListInfo[0]){
					case "all":
						if(fileList.length > 0){
							for(File _file: fileList){
								if(!references.containsKey(_file.getName())){
									references.put(_file.getName(),_file);
									System.out.println(_file.getName());
								}else{
									references.put(_file.getName()+_file.getPath().split(".")[1],_file);
									System.out.println(_file.getName()+_file.getPath().split(".")[1]);
								}
							}
						}else{
							System.err.println("Error ["+i+"]: There is not 1 or more files in the specified directory of "+fileListPath.getPath()+".");
						}
						break;
					case "recursive":
						if(fileList.length > 0 ){
							if(fileStorage == null){
								fileStorage = new ArrayList<File>();
							}
							recursive(fileListInfo[1]);
							for(File file: fileStorage){
								System.out.println(file.getName());
								references.put(file.getName(), file);
							}
							fileStorage.clear();
						}
					break;
					case "none":
						break;
					}
				}else{
					System.err.println("Error ["+i+"]: File path does not exist.");
				}
 			break;	
			}
		}
		if(_lightingType == lightingType.ambient){
			Game.setAmbientLight(ambientLight, false);
		}else{
			Game.setAmbientLight(ambientLight, true);
		}
		if(clearColorSet){
			Game.setClearColor(clearColor);
		}
		references.clear();
	}
	/**Create a game object based on file
	 * 
	 * @param file the file of the GameObject settings
	 * @return the final converted GameObject
	 */
	private GameObject gameObjectFromFile(File file){
		GameObject gameObject = new GameObject();
		//TODO
		return gameObject;
	}
	/**List all of the files and subfiles from each subfolder
	 * found til there are no more files to list.
	 * 
	 * @param path the path to recursively check
	 */
	private void recursive(String path){
		File root = new File(path);
		File[] list = root.listFiles();
		if(list.length > 0){
			for(File file : list){
				if(file.isDirectory()){
					recursive(file.getPath());
				}else if(file.isFile()){
					fileStorage.add(file);
				}
			}
		}
	}
	
	
}
